Skip to content

feat(detectors): add Rancher/Cattle token detector - #4960

Open
toor11 wants to merge 7 commits into
trufflesecurity:mainfrom
toor11:feat/rancher-token-detector
Open

toor11 wants to merge 7 commits into
trufflesecurity:mainfrom
toor11:feat/rancher-token-detector

Conversation

@toor11

@toor11 toor11 commented May 12, 2026 •

Copy link
Copy Markdown

Summary

Closes #4622. Adds a detector for Rancher API tokens (used by the Rancher Kubernetes management platform, deployed at 37,000+ organizations).

Detection Strategy

Tokens are anchored to known Rancher/Cattle variable names to avoid false positives on generic [a-z0-9]{54,64} strings (as flagged in the issue):

CATTLE_TOKEN, RANCHER_TOKEN, CATTLE_BOOTSTRAP_PASSWORD, RANCHER_API_TOKEN, RANCHER_SECRET_KEY

Regex pattern:

(?i)(?:CATTLE_TOKEN|RANCHER_TOKEN|CATTLE_BOOTSTRAP_PASSWORD|RANCHER_API_TOKEN|RANCHER_SECRET_KEY)[\w]*\s*[=:]\s*["']?([a-z0-9]{54,64})["']?

Verification

Verification requires a live Rancher server URL (CATTLE_SERVER) which is not available at scan time. Matched tokens are returned as unverified. A future enhancement could extract CATTLE_SERVER from the same context chunk and attempt GET {server}/v3 with Authorization: Bearer {token}.

Changes

  • pkg/detectors/rancher/rancher.go — detector implementation
  • pkg/detectors/rancher/rancher_test.go — pattern tests (env file, quoted values, no-context rejection, length rejection)
  • proto/detector_type.proto — Rancher = 1050
  • pkg/pb/detector_typepb/detector_type.pb.go — generated enum update
  • pkg/engine/defaults/defaults.go — registered &rancher.Scanner{}

Test Results

ok  github.com/trufflesecurity/trufflehog/v3/pkg/detectors/rancher  0.391s

Note

Low Risk
Additive detector-only change with tests and enum registration; no changes to scanning engine behavior beyond enabling a new detector type.

Overview
Adds a Rancher secret detector so TruffleHog can flag Rancher/Cattle API tokens in repos and configs.

Detection is context-aware: tokens must appear next to known names (CATTLE_TOKEN, RANCHER_TOKEN, CATTLE_BOOTSTRAP_PASSWORD, RANCHER_API_TOKEN, RANCHER_SECRET_KEY) with =/: separators and optional quotes, and the value must match 54–64 lowercase alphanumeric characters. Duplicates are deduped; hits are unverified because validation would need a live CATTLE_SERVER URL at scan time.

The scanner is wired into the default engine and exposed as DetectorType_Rancher (1072) via proto/generated enum updates. Tests cover env files, quoted/JSON values, and negative cases (wrong key, length, uppercase token).

Reviewed by Cursor Bugbot for commit c1dc235. Bugbot is set up for automated code reviews on this repo. Configure here.

@toor11
toor11 requested review from a team May 12, 2026 14:32
@toor11
toor11 requested a review from a team as a code owner May 12, 2026 14:32
@CLAassistant

CLAassistant commented May 12, 2026 •

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

Comment thread pkg/detectors/rancher/rancher.go Outdated
Comment thread pkg/detectors/rancher/rancher.go Outdated
Comment thread pkg/detectors/rancher/rancher.go Outdated
Comment thread pkg/engine/defaults/defaults.go Outdated
@gugacyber

Copy link
Copy Markdown

Nice work on this detector, the regex scoping of (?i:PREFIX) and the \b boundary fix are exactly right.
One thing worth checking: DetectorType_Rancher = 1050 may conflict with DetectorType_GitLabOauth2 = 1050 which was registered in a recent merge (#4950s range). Worth verifying the enum value against current main.
Also noticed the Scanner struct doesn't implement Description() string, other detectors in the codebase include it (e.g. stripe.go line 83). Not a blocker but keeps things consistent.
Overall the detection logic looks solid. The anchored variable name approach is the right call for a generic-looking token format like this.

@toor11
toor11 requested a review from a team May 28, 2026 21:29
@toor11

toor11 commented May 31, 2026

Copy link
Copy Markdown
Author

Thanks for the careful review, @gugacyber! 🙏 Both of your points are handled:

  • Enum value: Rancher is currently 1053 in detector_type.proto, and I verified there are no duplicate enum values — the generated detector_type.pb.go matches at DetectorType_Rancher = 1053, so there is no collision with GitLabOauth2 = 1050.
  • Description(): implemented on the Scanner struct (pkg/detectors/rancher/rancher.go L58–61), consistent with the other detectors.

The Cursor Bugbot items (scoped (?i:...), the \b boundary, and alphabetical ordering in defaults.go) were addressed in the earlier commits. I think it is ready for another look whenever a maintainer has a moment — thanks again for the thoughtful feedback!

@toor11
toor11 requested a review from a team May 31, 2026 20:17
@toor11 toor11 mentioned this pull request Jun 1, 2026
@toor11

toor11 commented Jul 9, 2026

Copy link
Copy Markdown
Author

@MuneebUllahKhan222 — apologies for the direct ping, and please redirect me if this isn't yours. This PR (adds the Rancher/Cattle token detector requested in #4622) has been open since May 12 without a reviewer assigned, and I believe it's ready.

Status

  • CLA signed.
  • All four Cursor Bugbot findings addressed: (?i:...) scoped to the variable-name prefix only (token capture stays case-sensitive), \b boundary so a longer string can't match on a truncated 64-char prefix, results returned as unverified (Verified=false, no VerificationError) since there's no live verification path, and import + scanner registration placed alphabetically between ramp and rapidapi.
  • Review feedback from @gugacyber addressed.
  • As of my last rebase (Jul 6), go test ./pkg/detectors/rancher/ and go test ./pkg/engine/defaults/ both passed.

On the conflict

The only thing marking this conflicting is the DetectorType enum value. Since the numbers are handed out next-sequentially, every open detector PR contests the same one, so an unmerged PR can't hold a number: Rancher has already been renumbered twice (1050 → 1053 → 1058), each time displaced by a detector that merged first — most recently NewRelicInsightsInsertKey took 1058 in #4778. It would be 1062 today, and it will drift again the next time a detector lands.

Rather than keep rebasing into a value that's contested by construction, I'd rather do it once, when it actually counts: whenever you're ready to look at this — or just start a review — I'll renumber to the next free value and push straight away so it lands clean.

Happy to make any other changes you'd like.

@toor11
toor11 force-pushed the feat/rancher-token-detector branch from 43a667b to fd7ca91 Compare September 4, 2026 00:08

@cursor cursor Bot left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stale Bugbot comment from a previous run.

Comment thread pkg/detectors/rancher/rancher.go Outdated
Detects Rancher API tokens by matching common Rancher/Cattle variable
names (CATTLE_TOKEN, RANCHER_TOKEN, CATTLE_BOOTSTRAP_PASSWORD,
RANCHER_API_TOKEN, RANCHER_SECRET_KEY) followed by a 54-64 char
lowercase alphanumeric token.

Anchoring detection to known variable names avoids false positives on
generic [a-z0-9]{54,64} strings. Verification requires a live Rancher
server URL (CATTLE_SERVER) which is not available at scan time, so
matched tokens are flagged as unverified.

Closes trufflesecurity#4622
verifyRancherToken was returning a non-nil error, causing
SetVerificationError to mark every result as unknown instead of
unverified. Tokens were silently dropped unless --results=unknown
was set. Returning (false, nil) correctly classifies them as
unverified.
…re case-sensitive

The global (?i) flag was widening the [a-z0-9]{54,64} capture group to
also match uppercase letters, causing false positives on uppercase strings.
Rancher tokens are lowercase alphanumeric only.

Replace (?i)(?:PREFIX) with (?i:PREFIX) so case-insensitivity applies
only to the variable name prefix, matching the pattern used by
azure_storage and other detectors in the codebase.

Added an uppercase token test case to assert the capture group
remains case-sensitive.
…oundary, and ordering

- Add missing context import (was causing build failure)
- Add \b after token capture group to prevent matching first 64 chars
  of tokens longer than 64 chars (false positive on truncated values)
- Drop unused verify scaffolding (net/http, verifyRancherToken, defaultClient)
  so results are correctly classified as unverified, not unknown
- Fix alphabetical ordering of rancher import and registration in defaults.go
  (ramp < rancher)
- Add test case for over-length token rejection
Allow an optional quote between the variable name and the separator so
quoted keys like `"CATTLE_TOKEN": "<token>" match. Adds JSON test cases.
@toor11
toor11 force-pushed the feat/rancher-token-detector branch from 1139598 to 03eae92 Compare September 13, 2026 13:56

@cursor cursor Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.

Fix All in Cursor

Reviewed by Cursor Bugbot for commit 40de802. Configure here.

Comment thread pkg/pb/detector_typepb/detector_type.pb.go Outdated
@toor11

toor11 commented Sep 28, 2026

Copy link
Copy Markdown
Author

Fixed — that was a leftover fragment of the >>>>>>> main marker from the rebase conflict resolution: the rawDesc length-prefix line was deleted along with the markers and main stayed behind, so the descriptor was truncated and the file could not build.

Restored the line with 0xa2, 0x8c, 0x01 (= 17954 = main's 17940 + the 14 Rancher entry bytes) in c1dc235. Verified: gofmt clean, go build OK, DetectorType(1072).String() == "Rancher" with neighbors intact, go test on the rancher detector and engine defaults passes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Rancher Tokens

3 participants